package com.newly.center.business.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.newly.api.sys.feign.AuthEntityClient;
import com.newly.center.business.service.MQTTDeviceService;
import com.newly.common.base.constants.AuthConstant;
import com.newly.common.base.entity.R;
import com.newly.common.base.entity.auth.ICurrentTenant;
import com.newly.common.base.entity.business.Po.CheckRecord;
import com.newly.common.base.entity.business.Po.Media;
import com.newly.common.base.entity.business.Po.Site;
import com.newly.common.base.entity.business.Vo.MqttDeviceVo;
import com.newly.common.base.entity.device.po.DevicePo;
import com.newly.common.base.entity.sys.dict.po.DictPo;
import com.newly.common.core.utils.RequestUtils;
import com.newly.common.mapper.business.CheckRecordMapper;
import com.newly.common.mapper.business.MediaMapper;
import com.newly.common.mapper.business.SiteMapper;
import com.newly.common.mapper.sys.DeviceMapper;
import com.newly.common.mapper.sys.DictMapper;
import com.newly.driver.mqtt.utils.MqttUtils;
import com.newly.driver.mqtt.utils.ReturnResult;
import com.newly.transfer.redis.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Service("mqttDeviceService")
public class MQTTDeviceServiceImpl extends ServiceImpl<DeviceMapper, DevicePo> implements MQTTDeviceService {
    @Autowired
    RedisUtils redisUtils;

    //    @Autowired
//    MQTTService mqttService;
    @Autowired
    SiteMapper siteMapper;
    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    DictMapper dictMapper;
    @Autowired
    CheckRecordMapper checkRecordMapper;
    @Autowired
    MediaMapper mediaMapper;

    @Autowired
    private AuthEntityClient authEntityClient;

    @Autowired
    private RequestUtils requestUtils;

    @Override
    public R getDeviceFlvUrl(String id, String type) {
        DictPo dictPo = dictMapper.selectById(49);
        if (dictPo == null || !"srsurl".equals(dictPo.getCode())) {
            return R.fail("未配置视频服务器参数");
        }

        DevicePo devicePo = deviceMapper.selectById(Long.parseLong(id));
        if (devicePo == null || devicePo.getGbId() == null) {
            return R.fail("设备未配置视频通道编码");
        }
        if ("0".equals(devicePo.getDeviceStatus())) {
            return R.fail(2, "设备离线");
        }
//        List<DevicePo> devicePos = deviceMapper.selectList(new LambdaQueryWrapper<DevicePo>().eq(DevicePo::getProductKey, devicePo.getProductKey()).eq(DevicePo::getType, 1));
//        if(devicePos.size()==0||devicePos.get(0).getGbId()==null){
//            return R.failed("设备未配置网关SIP用户名");
//        }
//        String url ="";
//
//        DictPo dictPo2 = dictMapper.selectById(53);
//        if("webrtc".equals(dictPo2.getValue())){
//            url = "webrtc://"+dictPo.getValue().split(":")[0]+":1985/live/"+devicePos.get(0).getGbId()+"@"+devicePo.getGbId();
//        }else {
//            url = "http://"+dictPo.getValue()+"/live/"+devicePos.get(0).getGbId()+"@"+devicePo.getGbId()+".flv";
//        }
        String url = "";

        DictPo dictPo2 = dictMapper.selectById(53);
        if ("webrtc".equals(dictPo2.getValue())) {
            url = "webrtc://" + dictPo.getValue().split(":")[0] + ":1985/live/" + devicePo.getGbId();
        } else {
            url = "http://" + dictPo.getValue() + "/live/" + devicePo.getGbId() + ".flv";
        }

        return R.ok(url);

    }

    @Override
    public List<String> getDateOfExistenceOfMedia(String siteId, String startDate, String endDate) {
        List<String> deviceIds = this.getDeviceIdsBySiteId(siteId);

        List<String> dates = new ArrayList<>();
        List<CheckRecord> checkRecordList = this.checkRecordMapper.selectList(new LambdaQueryWrapper<CheckRecord>()
                .like(CheckRecord::getDeviceId, deviceIds.get(0)).between(CheckRecord::getCreateTime, startDate, endDate));
        if (ObjectUtil.isEmpty(checkRecordList))
            return dates;
        List<Integer> ids = checkRecordList.stream().map(CheckRecord::getId).collect(Collectors.toList());
        List<Media> mediaList = this.mediaMapper.selectList(new LambdaQueryWrapper<Media>().in(Media::getOrderId, ids).eq(Media::getType, 2));
        if (ObjectUtil.isEmpty(mediaList))
            return dates;
        //设置时间格式为yyyy-MM-dd
        mediaList = mediaList.stream().peek(p ->
                p.setCreateTime(new DateTime(p.getCreateTime()).toString(DatePattern.NORM_DATE_FORMAT))).collect(Collectors.toList());
        //按日期分组
        Map<String, List<Media>> map = mediaList.stream().collect(Collectors.groupingBy(Media::getCreateTime));
        for (Map.Entry<String, List<Media>> entry : map.entrySet()) {
            if (entry.getValue().size() > 0)
                dates.add(entry.getKey());
        }
        return dates;
    }

    @Override
    public List<Map<String, String>> getDeviceHistoryFlvUrl(String date, String siteId) {
        List<String> deviceIds = this.getDeviceIdsBySiteId(siteId);

        List<Map<String, String>> urls = new ArrayList<>();
        String offDate = DateUtil.offsetDay(new DateTime(date, DatePattern.NORM_DATE_FORMAT), 1).toString(DatePattern.NORM_DATE_FORMAT);
        List<CheckRecord> checkRecordList = this.checkRecordMapper.selectList(new LambdaQueryWrapper<CheckRecord>().between(CheckRecord::getCreateTime, date, offDate).like(CheckRecord::getDeviceId, deviceIds.get(0)));
        if (ObjectUtil.isEmpty(checkRecordList))
            return urls;
        List<Integer> ids = checkRecordList.stream().map(CheckRecord::getId).collect(Collectors.toList());
        List<Media> mediaList = this.mediaMapper.selectList(new LambdaQueryWrapper<Media>().in(Media::getOrderId, ids).eq(Media::getType, 2));
        /*if (ObjectUtil.isEmpty(mediaList))
            throw new NewlyException("没有找到设备的相关媒体文件，请联系管理员");*/
        if (ObjectUtil.isEmpty(mediaList))
            return urls;
        for (Media media : mediaList) {
            Map<String, String> map = new HashMap<>();
            map.put("createTime", media.getCreateTime());
            map.put("url", media.getPictureUrl());
            urls.add(map);
        }
        return urls;
    }

    /**
     * 获取网点下摄像头设备productKey
     * @param siteId
     * @return
     */
    public List<String> getDeviceIdsBySiteId(String siteId) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        currentTenant.assertIncludeEntity(AuthConstant.AuthEntityType.SITE, siteId, "当前用户无此网点");

        List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.DEVICE);

        List<String> deviceIds = deviceMapper.selectList(
                Wrappers.lambdaQuery(DevicePo.class)
                        .select(DevicePo::getProductKey)
                        .eq(DevicePo::getType, 3)
                        .eq(DevicePo::getSiteId, siteId)
                        .in(DevicePo::getId, entityIds)
        ).stream().map(DevicePo::getProductKey).collect(Collectors.toList());

        return deviceIds;
    }

    @Override
    public JSONArray getLivingGateway() {
        JSONArray removeList = new JSONArray("[]");
        String gatewayStr = redisUtils.get("mqttGateway", String.class);
        JSONArray gateway = JSONUtil.parseArray(gatewayStr);
        for (Object item : gateway) {
            String token = item.toString();
            if (token == null || "".equals(token)) {
                removeList.add(item + "");
            }
        }
        gateway.removeAll(removeList);
        redisUtils.set("mqttGateway", JSONUtil.toJsonStr(gateway));
        List<Site> sites = siteMapper.selectList(new QueryWrapper<Site>().lambda());
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> deviceIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.DEVICE);

        List<DevicePo> devicePos = deviceMapper.selectList(new QueryWrapper<DevicePo>().lambda()
                .in(DevicePo::getId, deviceIds)
                .in(DevicePo::getProductKey, gateway)
                .eq(DevicePo::getType, 1));
        //设置检测站点区域名称
        devicePos = devicePos.stream().map(p -> sites.stream().filter(m ->
                Objects.equals(p.getSiteId(), m.getId())).findFirst()
                .map(m -> {
                    p.setSiteName(m.getName());
                    return p;
                }).orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        gateway = new JSONArray("[]");
        for (DevicePo item : devicePos) {
            Map data = new HashMap<>();
            data.put("name", item.getName());
            data.put("id", item.getProductKey());
            gateway.add(data);
        }
        return gateway;
    }

    @Override
    public R modifyVideoId(MqttDeviceVo data) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> deviceIds = new ArrayList<>();
        deviceIds.add(data.getId() + "");
        currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.DEVICE, deviceIds);
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id", data.getId());
        updateWrapper.set("gb_id", data.getGbId());
        int update = deviceMapper.update(null, updateWrapper);
        if (update > 0) {
            return R.ok("修改成功");
        } else {
            return R.fail("修改失败");
        }
    }


    @Override
    public R search(MqttDeviceVo data) {
        String token = redisUtils.get("mqtt" + data.getProductKey(), String.class);
        String requestTopic = "/sys/device/" + data.getProductKey() + "/command/request/request-id=0x10000002";
        String responseTopic = "/sys/device/" + data.getProductKey() + "/command/response/request-id=0x10000002";

        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", data.getProductKey());
        result.put("token", token);

        MqttUtils.publishMessage(requestTopic, result, 1);

        return ReturnResult.getResult(responseTopic, redisUtils);
    }

    @Override
    public R add(MqttDeviceVo data) {
        String token = redisUtils.get("mqtt" + data.getProductKey(), String.class);
        String requestTopic = "/sys/device/" + data.getProductKey() + "/command/request/request-id=0x10000003";
        String responseTopic = "/sys/device/" + data.getProductKey() + "/command/response/request-id=0x10000003";

        String a2 = data.getProductKey();
        String a = "1";
        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", data.getProductKey());
        result.put("token", token);

        JSONObject params = new JSONObject();
        params.put("slot", data.getSlot());

        JSONObject params2 = new JSONObject();
        params2.put("ip", data.getIp());
        params2.put("port", data.getPort());
        params2.put("type", data.getType());
        params2.put("username", data.getUsername());
        params2.put("password", data.getPassword());
        params2.put("protocol", data.getProtocol());
        params2.put("channel-used", data.getChannelUsed());
        params2.put("channel-max", data.getChannelMax());
        params2.put("channel-support", data.getChannelSupport());
        params2.put("type-alias", data.getTypeAlias());

        params.put("device", params2);
        result.put("params", params);

        MqttUtils.publishMessage(requestTopic, result, 1);

        R response = ReturnResult.getResult(responseTopic, redisUtils);
        if (response.getCode() == 0) {
            DevicePo gateway = deviceMapper.selectOne(new QueryWrapper<DevicePo>().lambda().eq(DevicePo::getType, 1).eq(DevicePo::getProductKey, data.getProductKey()));
            DevicePo devicePo = new DevicePo();
            String slotStr = JSONUtil.parseObj(response.getData()).getStr("slot");
            devicePo.setSlot(Integer.parseInt(slotStr));
            devicePo.setIp(data.getIp());
            devicePo.setPort(data.getPort());
            devicePo.setGatewayType(data.getType());
            devicePo.setUsername(data.getUsername());
            devicePo.setPassword(data.getPassword());
            devicePo.setProtocol(data.getProtocol());
            devicePo.setChannelUsed(JSONUtil.toJsonStr(data.getChannelUsed()));
            devicePo.setChannelMax(data.getChannelMax());
            devicePo.setChannelSupport(JSONUtil.toJsonStr(data.getChannelSupport()));
            devicePo.setSiteId(gateway.getSiteId());
            devicePo.setName(data.getName());
            devicePo.setProductKey(data.getProductKey());
            devicePo.setType(3);
            devicePo.setCreateTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
            devicePo.setTypeAlias(data.getTypeAlias());
            int insert = deviceMapper.insert(devicePo);
            if (insert > 0) {
                authEntityClient.bind(AuthConstant.AuthEntityType.DEVICE, Arrays.asList(devicePo.getId().toString()));
            }
        }
        return response;
    }

    @Override
    public R delete(List<String> ids) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.DEVICE, ids);

        List<DevicePo> devicePos = deviceMapper.selectBatchIds(ids);
        Map<String, List<DevicePo>> collect = devicePos.stream().collect(Collectors.groupingBy(DevicePo::getProductKey));
        for (String productKey : collect.keySet()) {
            List<DevicePo> deviceList = collect.get(productKey);
            Integer[] slotListTmp = deviceList.stream().map(x -> x.getSlot())
                    .collect(Collectors.toList()).toArray(new Integer[deviceList.size()]);
            int[] slotList = Arrays.stream(slotListTmp).mapToInt(x -> x).toArray();
            R deleteResult = mqttDdelete(productKey, slotList);
            if (deleteResult.getCode() == 0) {
                deviceMapper.delete(new QueryWrapper<DevicePo>().lambda()
                        .in(DevicePo::getSlot, slotListTmp).eq(DevicePo::getProductKey, productKey));
            } else {
                return R.fail("删除失败");
            }
        }
        return R.ok("删除成功");
    }

    @Override
    public R deleteCamera(MqttDeviceVo data, int slot, int[] channelIndex) {
        String token = redisUtils.get("mqtt" + data.getProductKey(), String.class);
        String requestTopic = "/sys/device/" + data.getProductKey() + "/command/request/request-id=0x10000005";
        String responseTopic = "/sys/device/" + data.getProductKey() + "/command/response/request-id=0x10000005";

        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", data.getProductKey());
        result.put("token", token);

        JSONObject params = new JSONObject();
        params.put("slot", slot);
        params.put("channel-index", channelIndex);
        result.put("params", params);

//        MqttUtils.publishMessage(requestTopic, result, 1);
        R response = ReturnResult.getResult(responseTopic, redisUtils);
        if (response.getCode() == 0) {
            int index = channelIndex[0];
            deviceMapper.delete(new QueryWrapper<DevicePo>().lambda()
                    .eq(DevicePo::getSlot, slot).eq(DevicePo::getChannelUsed, index)
            );

        }
        return response;
    }

    @Override
    public R modify(MqttDeviceVo data) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> deviceIds = new ArrayList<>();
        deviceIds.add(data.getId() + "");
        currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.DEVICE, deviceIds);
        String token = redisUtils.get("mqtt" + data.getProductKey(), String.class);
        String requestTopic = "/sys/device/" + data.getProductKey() + "/command/request/request-id=0x10000006";
        String responseTopic = "/sys/device/" + data.getProductKey() + "/command/response/request-id=0x10000006";

        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", data.getProductKey());
        result.put("token", token);

        JSONObject params = new JSONObject();
        params.put("slot", data.getSlot());
        params.put("ip", data.getIp());
        params.put("port", data.getPort());
        params.put("type", data.getType());
        params.put("username", data.getUsername());
        params.put("password", data.getPassword());
        params.put("protocol", data.getProtocol());
        params.put("channel-used", data.getChannelUsed());
        params.put("channel-max", data.getChannelMax());
        params.put("channel-support", data.getChannelSupport());
        params.put("type-alias", data.getTypeAlias());

        result.put("params", params);

        MqttUtils.publishMessage(requestTopic, result, 1);
        R response = ReturnResult.getResult(responseTopic, redisUtils);
        if (response.getCode() == 0) {
            List<DevicePo> devicePos = deviceMapper.selectList(new QueryWrapper<DevicePo>().lambda()
                    .eq(DevicePo::getSlot, data.getSlot()).ne(DevicePo::getType, 1).eq(DevicePo::getProductKey, data.getProductKey()));
            DevicePo devicePo = new DevicePo();
            if (devicePos.size() != 0) {
                devicePo = devicePos.get(0);
            }
            devicePo.setSlot(data.getSlot());
            devicePo.setIp(data.getIp());
            devicePo.setPort(data.getPort());
            devicePo.setGatewayType(data.getType());
            devicePo.setUsername(data.getUsername());
            devicePo.setPassword(data.getPassword());
            devicePo.setProtocol(data.getProtocol());
            devicePo.setChannelUsed(JSONUtil.toJsonStr(data.getChannelUsed()));
            devicePo.setChannelMax(data.getChannelMax());
            devicePo.setChannelSupport(JSONUtil.toJsonStr(data.getChannelSupport()));
            devicePo.setName(data.getName());
            devicePo.setTypeAlias(data.getTypeAlias());
            deviceMapper.updateById(devicePo);
        }
        return response;
    }

    @Override
    public R modifyGateway(MqttDeviceVo data) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> deviceIds = new ArrayList<>();
        deviceIds.add(data.getId() + "");
        currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.DEVICE, deviceIds);

        List<DevicePo> devicePos = deviceMapper.selectList(new QueryWrapper<DevicePo>().lambda()
                .eq(DevicePo::getSlot, data.getSlot()).eq(DevicePo::getId, data.getId()));
        DevicePo devicePo = new DevicePo();
        if (devicePos.size() != 0) {
            devicePo = devicePos.get(0);
        }
        devicePo.setSiteId(Long.parseLong(data.getSiteId()));
        devicePo.setGbId(data.getGbId());
//        devicePo.setSlot(data.getSlot());
//        devicePo.setIp(data.getIp());
//        devicePo.setPort(data.getPort());
//        devicePo.setGatewayType(data.getType());
//        devicePo.setUsername(data.getUsername());
//        devicePo.setPassword(data.getPassword());
//        devicePo.setProtocol(data.getProtocol());
//        devicePo.setChannelUsed(JSONUtil.toJsonStr(data.getChannelUsed()));
//        devicePo.setChannelMax(data.getChannelMax());
//        devicePo.setChannelSupport(JSONUtil.toJsonStr(data.getChannelSupport()));
        devicePo.setName(data.getName());
        int update = 0;
        if (devicePos.size() != 0) {
            update = deviceMapper.updateById(devicePo);
            deviceMapper.update(null, new UpdateWrapper<DevicePo>().lambda()
                    .eq(DevicePo::getProductKey, devicePo.getProductKey()).set(DevicePo::getSiteId, devicePo.getSiteId()));
        } else {
            update = deviceMapper.insert(devicePo);
        }
        if (update > 0) {
            return R.ok("修改成功");
        } else {
            return R.fail("修改失败");
        }
    }

    @Override
    public R deleteGateway(List<String> ids) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.DEVICE, ids);

        List<DevicePo> devicePos = deviceMapper.selectBatchIds(ids);
        List<DevicePo> collect = devicePos.stream().filter(x -> x.getType() == 1).collect(Collectors.toList());
        if (collect.size() > 0) {
            return R.fail("删除类型错误,非网关");
        }
        int delete = deviceMapper.deleteBatchIds(ids);
        if (delete > 0) {
            return R.fail("删除失败");
        } else {
            return R.ok("删除成功");
        }
    }

    @Override
    public R getList(MqttDeviceVo data, int[] slot) {
        String token = redisUtils.get("mqtt" + data.getProductKey(), String.class);
        String requestTopic = "/sys/device/" + data.getProductKey() + "/command/request/request-id=0x10000007";
        String responseTopic = "/sys/device/" + data.getProductKey() + "/command/response/request-id=0x10000007";
        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", data.getProductKey());
        result.put("token", token);

        result.put("slot", slot);

        MqttUtils.publishMessage(requestTopic, result, 1);
        R response = ReturnResult.getResult(responseTopic, redisUtils);
        if (response.getCode() == 0) {

        }
        return response;
    }

    @Override
    public R deviceSync(MqttDeviceVo data) {
        String token = redisUtils.get("mqtt" + data.getProductKey(), String.class);
        String requestTopic = "/sys/device/" + data.getProductKey() + "/command/request/request-id=0x10000007";
        String responseTopic = "/sys/device/" + data.getProductKey() + "/command/response/request-id=0x10000007";
        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", data.getProductKey());
        result.put("token", token);

        String slot = "{\"slot\":null}";
        result.put("params", JSONUtil.parseObj(slot));

        MqttUtils.publishMessage(requestTopic, result, 1);
        R response = ReturnResult.getResult(responseTopic, redisUtils);
        if (response.getCode() == 0) {
            List<DevicePo> gatewayDevicePos = new ArrayList<>();
            List<DevicePo> devicePos = deviceMapper.selectList(new QueryWrapper<DevicePo>().lambda()
                    .eq(DevicePo::getProductKey, data.getProductKey()).eq(DevicePo::getType, 3));
            DevicePo gateway = deviceMapper.selectList(new QueryWrapper<DevicePo>().lambda()
                    .eq(DevicePo::getProductKey, data.getProductKey()).eq(DevicePo::getType, 1)).get(0);

            JSONObject jsonObject = JSONUtil.parseObj(response.getData());
            JSONArray result1 = jsonObject.getJSONArray("device-list");
            for (Object item : result1) {
                JSONObject itemDevice = JSONUtil.parseObj(item);
                String deviceSlot = itemDevice.getStr("slot");
                List<DevicePo> collect = devicePos.stream().filter(x -> deviceSlot.equals(x.getSlot() + "")).collect(Collectors.toList());
                if (collect.size() > 0) {
                    gatewayDevicePos.addAll(collect);
                } else {
                    DevicePo devicePo = new DevicePo();
                    devicePo.setSlot(itemDevice.getInt("slot"));
                    devicePo.setIp(itemDevice.getStr("ip"));
                    devicePo.setPort(itemDevice.getInt("port"));
                    devicePo.setGatewayType(1);
                    devicePo.setUsername("admin");
                    devicePo.setPassword("newly2021");
                    devicePo.setProtocol(itemDevice.getInt("protocol"));
                    devicePo.setChannelUsed(JSONUtil.toJsonStr(itemDevice.getStr("channel-used")));
                    devicePo.setChannelMax(itemDevice.getInt("channel-max"));
                    devicePo.setChannelSupport(JSONUtil.toJsonStr(itemDevice.getStr("channel-support")));
                    devicePo.setName("槽位" + deviceSlot + "摄像机");
                    devicePo.setTypeAlias(itemDevice.getInt("type-alias"));
                    devicePo.setDeviceStatus(itemDevice.getStr("state").equals("online") ? "1" : "0");
                    devicePo.setSiteId(gateway.getSiteId());
                    devicePo.setType(3);
                    devicePo.setIsDeleted("0");
                    devicePo.setIsAvailable("1");
                    devicePo.setProductKey(data.getProductKey());
                    deviceMapper.insert(devicePo);
                }
            }
            devicePos.removeAll(gatewayDevicePos);
            List<Long> deviceIdList = devicePos.stream().map(x -> x.getId()).collect(Collectors.toList());
            if (deviceIdList.size() > 0) {
                deviceMapper.deleteBatchIds(deviceIdList);
            }
        }
        return response;
    }

    @Override
    public R getDeviceList(String keyword, Integer deviceStatus, Long siteId, Integer type, Integer pageNum, Integer pageSize) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> deviceIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.DEVICE);
        if (ObjectUtil.isEmpty(deviceIds)) return null;

        Page<DevicePo> devicePage = new Page<DevicePo>(pageNum, pageSize);
        QueryWrapper<DevicePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("site_id");
        queryWrapper.eq(siteId != null, "site_id", siteId);
        queryWrapper.eq(deviceStatus != null, "device_status", deviceStatus);
        queryWrapper.eq(type != null, "type", type);
        queryWrapper.like(keyword != null, "name", keyword);
        queryWrapper.in("id", deviceIds);

        devicePage = deviceMapper.selectPage(devicePage, queryWrapper);
        List<DevicePo> records = devicePage.getRecords();
        List<Site> sites = siteMapper.selectList(new QueryWrapper<Site>().lambda());
        //设置站点名称、站点负责人、电话
        records = records.stream().map(p -> sites.stream().filter(m ->
                Objects.equals(p.getSiteId(), m.getId())).findFirst()
                .map(m -> {
                    p.setSiteName(m.getName());
                    p.setSiteAgent(m.getSiteAgent());
                    p.setPhone(m.getPhone());
                    return p;
                }).orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        devicePage.setRecords(records);
        return R.ok(devicePage);
    }

    @Override
    public R getDeviceTree(String keyword) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> deviceIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.DEVICE);
        if (ObjectUtil.isEmpty(deviceIds)) return null;
//        deviceIds = new ArrayList<>();
//        currentTenant.assertIncludeEntities(AuthConstant.AuthEntityType.DEVICE, deviceIds);


        List<Map<String, Object>> result = new ArrayList<>();

        Set<Long> siteIdsSet = siteMapper.selectList(
                Wrappers.lambdaQuery(Site.class)
                        .like(StrUtil.isNotBlank(keyword), Site::getName, keyword)
                        .eq(Site::getIsDeleted, 0)
        ).stream().map(Site::getId).collect(Collectors.toSet());

        LambdaQueryWrapper<DevicePo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(DevicePo::getCreateTime)
                .in(DevicePo::getId, deviceIds)
                .ne(DevicePo::getType, 1)
                .and(StrUtil.isNotBlank(keyword),
                        w -> w.like(DevicePo::getName, keyword).or()
                                .in(ObjectUtil.isNotEmpty(siteIdsSet), DevicePo::getSiteId, siteIdsSet)
                );

        List<DevicePo> devicePos = deviceMapper.selectList(queryWrapper);
        List<Long> siteIds = devicePos.stream().map(DevicePo::getSiteId).collect(Collectors.toList());
        if (siteIds.size() == 0) {
            return R.ok(result);
        }
        List<Site> sites = siteMapper.selectList(new QueryWrapper<Site>().lambda().in(Site::getId, siteIds));
        //设置站点名称
        devicePos = devicePos.stream().map(p -> sites.stream().filter(m ->
                Objects.equals(p.getSiteId(), m.getId())).findFirst()
                .map(m -> {
                    p.setSiteName(m.getName());
                    p.setSiteAgent(m.getSiteAgent());
                    p.setPhone(m.getPhone());
                    return p;
                }).orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        Map<String, List<DevicePo>> collect = devicePos.stream().collect(Collectors.groupingBy(DevicePo::getSiteName));
        for (String item : collect.keySet()) {
            Map<String, Object> data = new HashMap<>();
            data.put("site", item);
            data.put("device", collect.get(item));
            result.add(data);
        }

        return R.ok(result);
    }

    @Override
    public List<String> getUrlBySiteId(String siteId) {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> authDeviceIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.DEVICE);
        if (ObjectUtil.isEmpty(authDeviceIds)) return null;

        List<String> deviceIds = deviceMapper.selectList(
                Wrappers.lambdaQuery(DevicePo.class)
                        .in(DevicePo::getId, authDeviceIds)
                        .eq(DevicePo::getDeviceStatus, 1)
                        .eq(DevicePo::getIsAvailable, 1)
                        .eq(DevicePo::getIsDeleted, 0)
                        .eq(DevicePo::getSiteId, siteId)
                        .eq(DevicePo::getTypeAlias, 1)
        ).stream().map(d -> d.getId().toString()).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(deviceIds)) {
            return new ArrayList<>(0);
        }

        List<String> urls = deviceIds.stream().map(id -> {
                    String url = (String) getDeviceFlvUrl(id, null).getData();
                    return url;
                }
        ).collect(Collectors.toList());

        return urls;
    }

    @Override
    public List<DevicePo> getByIdsInAuth(List<String> deviceIds) {
        if (ObjectUtil.isEmpty(deviceIds)) return null;
        return deviceMapper.selectBatchIds(deviceIds);
    }

    private R mqttDdelete(String productKey, int[] slot) {
        String token = redisUtils.get("mqtt" + productKey, String.class);
        String requestTopic = "/sys/device/" + productKey + "/command/request/request-id=0x10000004";
        String responseTopic = "/sys/device/" + productKey + "/command/response/request-id=0x10000004";

        JSONObject result = new JSONObject();
        result.put("version", "1.0");
        result.put("id", productKey);
        result.put("token", token);

        JSONObject params = new JSONObject();
        params.put("slot", slot);
        result.put("params", params);

        MqttUtils.publishMessage(requestTopic, result, 1);
        return ReturnResult.getResult(responseTopic, redisUtils);
    }
}
